[bits 32]

extern _PrintError
extern _ServiceList

;|-------|---
;|Param  |
;|Local  |Function
;|si bp  |Frame
;|Stack  |
;|-------|---

;(Function Call)
;push {all parameters}
;(Function Entry)
;sub esp, {local variables' space}
;push esi
;push ebp
;lea ebp, [esp + 8]
;mov esi, {function address}
;(Function Body)
;......
;(Function End)
;pop ebp
;pop esi
;add esp, {all parameters' and local variables' space}

section .text
global _InterpreterEntry
_InterpreterEntry:
    mov esi, [esp + 4]
    ;mov esi, TestIns
    ;函数入口
    sub esp, 12h
    push esi
    push ebp
    lea ebp, [esp + 8]
    ;指令表
    prefetch [InstructionTable]
ZBack:
    xor eax, eax
Back:
    lodsb
    jmp dword [InstructionTable + eax * 4]
UndefinedError:
    push dword End - ErrorMsg
    push dword ErrorMsg
    call _PrintError
    add esp, 8
    jmp ZBack
FloatError:
    push dword ErrorMsg - FloatMsg
    push dword FloatMsg
    call _PrintError
    add esp, 8
    jmp ZBack
PushByte:
    movsx edx, byte [esi]
    inc esi
    push edx
    jmp Back
PushWord:
    movsx edx, word [esi]
    add esi, 2
    push edx
    jmp Back
PushDword:
    mov edx, [esi]
    add esi, 4
    push edx
    jmp Back
Load:
    lodsb
    push dword [ebp + eax * 4]
    jmp Back
Store:
    lodsb
    pop dword [ebp + eax * 4]
    jmp Back
KiSystemService:
    lodsb
    call dword [_ServiceList + eax * 4]
    push eax
    jmp ZBack
JumpShort:
    movsx edx, byte [esi]
    inc esi
    add esi, edx
    jmp Back
Add:
    pop edx
    add [esp], edx
    jmp Back
Sub:
    pop edx
    sub [esp], edx
    jmp Back
Mul:
    pop eax
    mul dword [esp]
    mov [esp], eax
    jmp ZBack
Div:
    pop edx
    pop eax
    div edx
    push eax
    jmp ZBack
Rem:
    pop edx
    pop eax
    div edx
    push edx
    jmp ZBack
And:
    pop edx
    and [esp], edx
    jmp Back
Or:
    pop edx
    or [esp], edx
    jmp Back
Xor:
    pop edx
    xor [esp], edx
    jmp Back
Not:
    not dword [esp]
    jmp Back
Inc:
    inc dword [esp]
    jmp Back
Dec:
    dec dword [esp]
    jmp Back
Addf:
    fld dword [esp]
    add esp, 4
    fadd dword [esp]
    fstp dword [esp]
    jmp Back
Subf:
    fld dword [esp]
    add esp, 4
    fsubr dword [esp]
    fstp dword [esp]
    jmp Back
Mulf:
    fld dword [esp]
    add esp, 4
    fmul dword [esp]
    fstp dword [esp]
    jmp Back
Divf:
    ;可选查错
    ;test dword [esp], 7FFFFFFFh
    ;jz FloatError;异常处理可以设置
    fld dword [esp]
    add esp, 4
    fdivr dword [esp]
    fstp dword [esp]
    jmp Back
i2f:
    fild dword [esp]
    fstp dword [esp]
    jmp Back
f2i:
    fld dword [esp]
    fistp dword [esp]
    jmp Back
CmpE:
    pop edx
    cmp [esp], edx
    sete [esp]
    jmp Back
CmpL:
    pop edx
    cmp [esp], edx
    setl [esp]
    jmp Back
CmpG:
    pop edx
    cmp [esp], edx
    setg [esp]
    jmp Back
CmpNE:
    pop edx
    cmp [esp], edx
    setne [esp]
    jmp Back
CmpNL:
    pop edx
    cmp [esp], edx
    setnl [esp]
    jmp Back
CmpNG:
    pop edx
    cmp [esp], edx
    setng [esp]
    jmp Back
Dup:
    push dword [esp]
    jmp Back
;没想到cmovcc一类指令源操作数不能为立即数,也许只能靠处理器mov乱序执行保证性能了
;条件分支跳转的性能消耗有点大,无条件跳转没有问题
Jumpcc:
    movsx ecx, byte [esi]
    inc esi
    add ecx, esi
    test byte [esp], 1
    cmovnz esi, ecx
    add esp, 4
    jmp Back
QSqrtInv:
    mov edx, [esp]
    sub dword [esp], 800000h
    mov ecx, 5F375A86h
    shr edx, 1
    sub ecx, edx
    mov [Temp], ecx
    fld dword [Temp]
    fld dword [esp]
    fmul
    fmul
    fsubr dword [ThreeHalfs]
    fmulp
    fstp dword [esp]
    jmp Back
Reflb:
    mov ebx, [esp]
    movsx edx, byte [ebx]
    mov [esp], edx
    jmp Back
Reflw:
    mov ebx, [esp]
    movsx edx, word [ebx]
    mov [esp], edx
    jmp Back
Refld:
    pop ebx
    push dword [ebx]
    jmp Back
Refsb:
    pop edx
    pop ebx
    mov [ebx], dl
    jmp Back
Refsw:
    pop edx
    pop ebx
    mov [ebx], dx
    jmp Back
Refsd:
    pop edx
    pop ebx
    mov [ebx], edx
    jmp Back
LoadIP:
    movsx edx, byte [esi]
    inc esi
    add edx, esi
    push edx
    jmp Back
Call:
    lodsb
    sub esp, eax
    movsx edx, byte [esi]
    inc esi
    push esi
    add esi, edx
    push ebp
    lea ebp, [esp + 8]
    jmp Back
Callf:
    lodsb
    sub esp, eax
    movzx edx, byte [esi]
    inc esi
    push esi
    mov ebx, [_ImportFunctionTable]
    mov esi, [ebx + edx * 4]
    push ebp
    lea ebp, [esp + 8]
    jmp Back
Ret:
    lodsb
    pop ebp
    pop esi
    add esp, eax
    jmp Back
Retn:
    pop edx
    shl edx, 2
    pop ebp
    pop esi
    add esp, edx
    jmp Back
Pop:
    add esp, 4
    jmp Back
Popn:
    lodsb
    add esp, eax
    jmp Back

section .data
;TestIns:
;    incbin "test.out"
FloatMsg:
    db "Unordered Float", 0Dh, 0Ah
ErrorMsg:
    db "Undefined Instruction", 0Dh, 0Ah
End:

;按照CPU缓存的行大小对齐
section .data align=64
InstructionTable:
    dd PushByte;0
    dd PushWord;1
    dd PushDword;2
    dd Load;3
    dd Store;4
    dd KiSystemService;5
    dd JumpShort;6
    dd Add;7
    dd Sub;8
    dd Mul;9
    dd Div;10
    dd Rem;11
    dd And;12
    dd Or;13
    dd Xor;14
    dd Not;15
    dd Inc;16
    dd Dec;17
    dd Addf;18
    dd Subf;19
    dd Mulf;20
    dd Divf;21
    dd i2f;22
    dd f2i;23
    dd CmpE;24
    dd CmpL;25
    dd CmpG;26
    dd CmpNE;27
    dd CmpNL;28
    dd CmpNG;29
    dd Dup;30
    dd Jumpcc;31
    dd QSqrtInv;32
    dd Reflb;33
    dd Reflw;34
    dd Refld;35
    dd Refsb;36
    dd Refsw;37
    dd Refsd;38
    dd LoadIP;39
    dd Call;40
    dd Callf;41
    dd Ret;42
    dd Retn;43
    dd Pop;44
    dd Popn;45
    times 0x100 - (($ - InstructionTable) / 4) dd UndefinedError
_ImportFunctionTable:
    dd 0
Temp:
    dd 0
ThreeHalfs:
    dd 3FC00000h
